home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / news / inn1.000 / inn1.4sec-linux-src.tar / inn / nnrpd / misc.c < prev    next >
C/C++ Source or Header  |  1993-03-18  |  9KB  |  458 lines

  1. /*  $Revision: 1.14 $
  2. **
  3. **  Miscellaneous support routines.
  4. */
  5. #include "nnrpd.h"
  6. #include "dbz.h"
  7. #if    defined(DO_NEED_TIME)
  8. #include <time.h>
  9. #endif    /* defined(DO_NEED_TIME) */
  10. #include <sys/time.h>
  11.  
  12.  
  13. #define ASCtoNUM(c)        ((c) - '0')
  14. #define CHARStoINT(c1, c2)    (ASCtoNUM((c1)) * 10 + ASCtoNUM((c2)))
  15. #define DaysInYear(y)        ((y % 4 ? 365 : 366))
  16.  
  17.  
  18. /*
  19. **  Parse a string into a NULL-terminated array of words; return number
  20. **  of words.  If argvp isn't NULL, it and what it points to will be
  21. **  DISPOSE'd.
  22. */
  23. int
  24. Argify(line, argvp)
  25.     char        *line;
  26.     char        ***argvp;
  27. {
  28.     register char    **argv;
  29.     register char    *p;
  30.     register int    i;
  31.  
  32.     if (*argvp != NULL) {
  33.     DISPOSE(*argvp[0]);
  34.     DISPOSE(*argvp);
  35.     }
  36.  
  37.     /*  Copy the line, which we will split up. */
  38.     while (ISWHITE(*line))
  39.     line++;
  40.     i = strlen(line);
  41.     p = NEW(char, i + 1);
  42.     (void)strcpy(p, line);
  43.  
  44.     /* Allocate worst-case amount of space. */
  45.     for (*argvp = argv = NEW(char*, i + 2); *p; ) {
  46.     /* Mark start of this word, find its end. */
  47.     for (*argv++ = p; *p && !ISWHITE(*p); )
  48.         p++;
  49.     if (*p == '\0')
  50.         break;
  51.  
  52.     /* Nip off word, skip whitespace. */
  53.     for (*p++ = '\0'; ISWHITE(*p); )
  54.         p++;
  55.     }
  56.     *argv = NULL;
  57.     return argv - *argvp;
  58. }
  59.  
  60.  
  61. /*
  62. **  Take a vector which Argify made and glue it back together with
  63. **  spaces between each element.  Returns a pointer to dynamic space.
  64. */
  65. char *
  66. Glom(av)
  67.     char        **av;
  68. {
  69.     register char    **v;
  70.     register char    *p;
  71.     register int    i;
  72.     char        *save;
  73.  
  74.     /* Get space. */
  75.     for (i = 0, v = av; *v; v++)
  76.     i += strlen(*v) + 1;
  77.  
  78.     for (save = p = NEW(char, i + 1), v = av; *v; v++) {
  79.     if (p > save)
  80.         *p++ = ' ';
  81.     p += strlen(strcpy(p, *v));
  82.     }
  83.  
  84.     return save;
  85. }
  86.  
  87.  
  88. /*
  89. **  Match a list of newsgroup specifiers against a list of newsgroups.
  90. **  func is called to see if there is a match.
  91. */
  92. BOOL
  93. PERMmatch(match, Pats, list)
  94.     register BOOL    match;
  95.     char        **Pats;
  96.     char        **list;
  97. {
  98.     register int    i;
  99.     register char    *p;
  100.  
  101.     if (Pats[0] == NULL)
  102.     return TRUE;
  103.  
  104.     for ( ; *list; list++)
  105.     for (i = 0; (p = Pats[i]) != NULL; i++) {
  106.         if (p[0] == '!') {
  107.         if (wildmat(*list, ++p))
  108.             match = FALSE;
  109.         }
  110.         else if (wildmat(*list, p))
  111.         match = TRUE;
  112.     }
  113.  
  114.     return match;
  115. }
  116.  
  117.  
  118. /*
  119. **  Check to see if user is allowed to see this article by matching
  120. **  Newsgroups line.
  121. */
  122. BOOL
  123. PERMartok(qp)
  124.     register QIOSTATE    *qp;
  125. {
  126.     static char        **grplist;
  127.     register char    *p;
  128.     register char    *q;
  129.     BOOL        found;
  130.  
  131.     if (!PERMspecified)
  132.     return PERMdefault;
  133.  
  134.     for (found = FALSE; ; ) {
  135.     p = QIOread(qp);
  136.     if (p == NULL) {
  137.         if (QIOtoolong(qp))
  138.         continue;
  139.         break;
  140.     }
  141.  
  142.     if (*p == '\n')
  143.         /* End of header */
  144.         break;
  145.     if (*p != 'N' && *p != 'n')
  146.         continue;
  147.     if ((q = strchr(p, ':')) == NULL)
  148.         continue;
  149.     *q = '\0';
  150.     if (caseEQ(p, "newsgroups")) {
  151.         found = NGgetlist(&grplist, q + 2);
  152.         break;
  153.     }
  154.     }
  155.     (void)QIOrewind(qp);
  156.  
  157.     if (!found)
  158.     /* No newgroups or null entry. */
  159.     return 1;
  160.  
  161.     return PERMmatch(PERMdefault, PERMlist, grplist);
  162. }
  163.  
  164.  
  165. /*
  166. **  Parse a date like yymmddhhmmss into a long.  Return -1 on error.
  167. */
  168. long
  169. NNTPtoGMT(av1, av2)
  170.     char        *av1;
  171.     char        *av2;
  172. {
  173.     /* Note that this is origin-one! */
  174.     static int        DaysInMonth[12] = {
  175.     0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30
  176.     };
  177.     register char    *p;
  178.     int            year;
  179.     int            month;
  180.     int            day;
  181.     int            hour;
  182.     int            mins;
  183.     int            secs;
  184.     register int    i;
  185.     long        seconds;
  186.     char        buff[6 + 6 + 1];
  187.  
  188.     if (strlen(av1) != 6 || strlen(av2) != 6)
  189.     return -1;
  190.     (void)sprintf(buff, "%s%s", av1, av2);
  191.     for (p = buff; *p; p++)
  192.     if (!CTYPE(isdigit, *p))
  193.         return -1;
  194.  
  195.     year  = CHARStoINT(buff[ 0], buff[ 1]);
  196.     month = CHARStoINT(buff[ 2], buff[ 3]);
  197.     day   = CHARStoINT(buff[ 4], buff[ 5]);
  198.     hour  = CHARStoINT(buff[ 6], buff[ 7]);
  199.     mins  = CHARStoINT(buff[ 8], buff[ 9]);
  200.     secs  = CHARStoINT(buff[10], buff[11]);
  201.  
  202.     if (month < 1 || month > 12
  203.      || day < 1 || day > 31
  204.      || mins < 0 || mins > 59
  205.      || secs < 0 || secs > 59)
  206.     return -1;
  207.     if (hour == 24) {
  208.     hour = 0;
  209.     day++;
  210.     }
  211.     else if (hour < 0 || hour > 23)
  212.     return -1;
  213.  
  214.     for (seconds = 0, year += 1900, i = 1970; i < year; i++)
  215.     seconds += DaysInYear(i);
  216.     if (DaysInYear(year) == 366 && month > 2)
  217.     seconds++;
  218.     while (--month > 0)
  219.     seconds += DaysInMonth[month];
  220.     seconds += day - 1;
  221.     seconds = 24 * seconds + hour;
  222.     seconds = 60 * seconds + mins;
  223.     seconds = 60 * seconds + secs;
  224.  
  225.     return seconds;
  226. }
  227.  
  228.  
  229. /*
  230. **  Convert local time (seconds since epoch) to GMT.
  231. */
  232. long
  233. LOCALtoGMT(t)
  234.     long    t;
  235. {
  236.     TIMEINFO    Now;
  237.  
  238.     (void)GetTimeInfo(&Now);
  239.     t += Now.tzone * 60;
  240.     return t;
  241. }
  242.  
  243.  
  244. /*
  245. **  Return the path name of an article if it is in the history file.
  246. **  Return a pointer to static data.
  247. */
  248. char *
  249. HISgetent(msg_id, fulldata)
  250.     char        *msg_id;
  251.     BOOL        fulldata;
  252. {
  253.     static BOOL        setup;
  254. #if    NNRP_DBZINCORE_DELAY > 0
  255.     static int        count = NNRP_DBZINCORE_DELAY;
  256. #endif    /* NNRP_DBZINCORE_DELAY > 0 */
  257.     static FILE        *hfp;
  258.     static char        path[BIG_BUFFER];
  259.     register char    *p;
  260.     register char    *q;
  261.     register int    i;
  262.     char        *save;
  263.     char        buff[BIG_BUFFER];
  264.     OFFSET_T        l;
  265.     datum        key;
  266.     datum        value;
  267.     struct stat        Sb;
  268.  
  269. #if    NNRP_DBZINCORE_DELAY > 0
  270.     if (count && --count == 0) {
  271.     if (setup) {
  272.         (void)dbmclose();
  273.         setup = FALSE;
  274.     }
  275.     (void)dbzincore(1);
  276.     }
  277. #endif    /* NNRP_DBZINCORE_DELAY > 0 */
  278.     if (!setup) {
  279.     if (dbminit(HISTORY) < 0) {
  280.         syslog(L_ERROR, "%s cant dbminit %s %m", ClientHost, HISTORY);
  281.         return NULL;
  282.     }
  283.     setup = TRUE;
  284.     }
  285.  
  286.     /* Set the key value, fetch the entry. */
  287.     for (p = key.dptr = msg_id; *p; p++)
  288.     if (*p == HIS_FIELDSEP || *p == '\n')
  289.         *p = HIS_BADCHAR;
  290.     key.dsize = p - key.dptr + 1;
  291.     value = dbzfetch(key);
  292.     if (value.dptr == NULL)
  293.     return NULL;
  294.     for (q = (char *)&l, p = value.dptr, i = sizeof l; --i >= 0; )
  295.     *q++ = *p++;
  296.  
  297.     /* Open history file if we need to. */
  298.     if (hfp == NULL) {
  299.     if ((hfp = fopen(HISTORY, "r")) == NULL) {
  300.         syslog(L_ERROR, "%s cant fopen %s %m", ClientHost, HISTORY);
  301.         return NULL;
  302.     }
  303.     CloseOnExec((int)fileno(hfp), TRUE);
  304.     }
  305.  
  306.     /* Seek and read. */
  307.     if (fseek(hfp, l, SEEK_SET) == -1) {
  308.     syslog(L_ERROR, "%s cant fseek to %ld %m", ClientHost, l);
  309.     return NULL;
  310.     }
  311.     if (fgets(buff, sizeof buff, hfp) == NULL) {
  312.     syslog(L_ERROR, "%s cant fgets from %ld %m", ClientHost, l);
  313.     return NULL;
  314.     }
  315.     if ((p = strchr(buff, '\n')) != NULL)
  316.     *p = '\0';
  317.  
  318.     /* Skip first two fields. */
  319.     if ((p = strchr(buff, '\t')) == NULL) {
  320.     syslog(L_ERROR, "%s bad_history at %ld for %s", ClientHost, l, msg_id);
  321.     return NULL;
  322.     }
  323.     if ((p = strchr(p + 1, '\t')) == NULL)
  324.     /* Article has expired. */
  325.     return NULL;
  326.     save = p + 1;
  327.  
  328.     /* Want the full data? */
  329.     if (fulldata) {
  330.     (void)strcpy(path, save);
  331.     for (p = path; *p; p++)
  332.         if (*p == '.')
  333.         *p = '/';
  334.     return path;
  335.     }
  336.  
  337.     /* Want something we can open; loop over all entries. */
  338.     for ( ; ; save = q + 1) {
  339.     if ((q = strchr(save, ' ')) != NULL)
  340.         *q = '\0';
  341.     for (p = save; *p; p++)
  342.         if (*p == '.')
  343.         *p = '/';
  344.     (void)sprintf(path, "%s/%s", _PATH_SPOOL, save);
  345.     if (stat(path, &Sb) >= 0)
  346.         return path;
  347.     if (q == NULL)
  348.         break;
  349.     }
  350.  
  351.     return NULL;
  352. }
  353.  
  354.  
  355. /*
  356. **  Parse a newsgroups line, return TRUE if there were any.
  357. */
  358. BOOL
  359. NGgetlist(argvp, list)
  360.     char        ***argvp;
  361.     char        *list;
  362. {
  363.     register char    *p;
  364.  
  365.     for (p = list; *p; p++)
  366.     if (*p == ',')
  367.         *p = ' ';
  368.  
  369.     return Argify(list, argvp) != 0;
  370. }
  371.  
  372.  
  373. /*
  374. **  Take an NNTP distribution list <d1,d2,...> and turn it into an array.
  375. */
  376. BOOL
  377. ParseDistlist(argvp, list)
  378.     char        ***argvp;
  379.     char        *list;
  380. {
  381.     static char        **argv;
  382.     register char    *p;
  383.  
  384.     if (list[0] != '<' || (p = strchr(&list[1], '>')) == NULL)
  385.     return FALSE;
  386.     *p = '\0';
  387.  
  388.     for (p = list + 1; *p; p++)
  389.     if (*p == ',')
  390.         *p = ' ';
  391.     (void)Argify(list + 1, &argv);
  392.     *argvp = argv;
  393.     return TRUE;
  394. }
  395.  
  396.  
  397. /*
  398. **  Read a line of input, with timeout.
  399. */
  400. READTYPE
  401. READline(start, size, timeout)
  402.     char        *start;
  403.     int            size;
  404.     int            timeout;
  405. {
  406.     static int        count;
  407.     static char        buffer[BUFSIZ];
  408.     static char        *bp;
  409.     register char    *p;
  410.     register char    *end;
  411.     struct timeval    t;
  412.     FDSET        rmask;
  413.     int            i;
  414.     char        c;
  415.  
  416.     for (p = start, end = &start[size - 1]; ; ) {
  417.     if (count == 0) {
  418.         /* Fill the buffer. */
  419.     Again:
  420.         FD_ZERO(&rmask);
  421.         FD_SET(STDIN, &rmask);
  422.         t.tv_sec = timeout;
  423.         t.tv_usec = 0;
  424.         i = select(STDIN + 1, &rmask, (FDSET *)NULL, (FDSET *)NULL, &t);
  425.         if (i < 0) {
  426.         if (errno == EINTR)
  427.             goto Again;
  428.         syslog(L_ERROR, "%s cant select %m", ClientHost);
  429.         return RTtimeout;
  430.         }
  431.         if (i == 0 || !FD_ISSET(STDIN, &rmask))
  432.         return RTtimeout;
  433.         count = read(STDIN, buffer, sizeof buffer);
  434.         if (count < 0) {
  435.         syslog(L_ERROR, "%s cant read %m", ClientHost);
  436.         return RTtimeout;
  437.         }
  438.         if (count == 0)
  439.         return RTeof;
  440.         bp = buffer;
  441.     }
  442.  
  443.     /* Process next character. */
  444.     count--;
  445.     c = *bp++;
  446.     if (c == '\n')
  447.         break;
  448.     if (p < end)
  449.         *p++ = c;
  450.     }
  451.  
  452.     /* If last two characters are \r\n, kill the \r as well as the \n. */
  453.     if (p > start && p < end && p[-1] == '\r')
  454.     p--;
  455.     *p = '\0';
  456.     return p == end ? RTlong : RTok;
  457. }
  458.